package com.kehutong.common.util;


import org.apache.commons.beanutils.BeanUtils;
import org.coraframework.bean.BeanException;
import org.coraframework.bean.Beans;
import org.coraframework.bean.valid.ValidResult;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.orm.Pool;
import org.coraframework.util.Objects;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;


/**
 * 集合工具类 List 工具类
 * @author: jian Ye
 **/

public class ListUtils {

    private static final Logger logger = LoggerFactory.getLogger(ListUtils.class);

    /**
     * 获得重复的元素
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> getDuplicateElements(List<T> list) {
        return list.stream()
                .collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b))
                .entrySet().stream()
                .filter(entry -> entry.getValue() > 1)
                .map(entry -> entry.getKey())
                .collect(Collectors.toList());
    }


    /**
     * 按照len的大小，将sourcesList切成多个list
     * @param sources
     * @param len
     * @param <T>
     * @return
     */
    public static<T> List<List<T>> splitList(List<T> sources, int len) {
        if (Objects.isEmpty(sources)) {
            return new ArrayList<>();
        }
        List<List<T>> result = new ArrayList<>();
        int size = sources.size();
        int count = (size + len - 1) / len;
        for (int i = 0; i < count; i++) {
            List<T> subList = sources.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }


    /**
     * 将list转为String，分隔符为第二个参数
     * @param separator 字符串分隔符
     * @author jian Ye
     * @Date  2021/8/1
     **/
    public static <T> String listToString(List<T> list, String separator) {
        if(Objects.isEmpty(list)){ return "";}
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < list.size(); i++) {
            stringBuilder.append(list.get(i));
            if(i < list.size()-1){
                stringBuilder.append(separator);
            }
        }
        return stringBuilder.toString();
    }


    /**
     * List集合数据深拷贝
     *
     * 例子：List<SysRoleVO> roleVOList = CopyListUtils.copyList(sysRoleList, SysRoleVO::new);
     * @param sources: 数据源类
     * @param target:  目标类
     * @author jian Ye
     * @return
     */
    public static <S, T> List<T> copyList(@NotNull List<S> sources, Supplier<T> target) {
        return copyListProperties(sources, target, null);
    }

    /**
     * List集合数据深拷贝
     *
     * 例子：List<SysRoleVO> roleVOList = CopyListUtils.copyList(sysRoleList, SysRoleVO::new); --报错的话用下面方法
     * 或者：List<MeterManage> manageDTOList = ListUtils.copyBeanList(list,  ()->Pool.newInstance(MeterManage.class));
     * @param sources: 数据源类
     * @param target:  目标类
     * @author jian Ye
     * @return
     */

    public static <S, T> List<T> copyBeanList(@NotNull List<S> sources, Supplier<T> target) {
        List<T> dataList = new ArrayList<>(sources.size());
        try {
            sources.forEach(item-> {
                T t = target.get();
                Beans.from((JSONObject)JSONObject.toJSON(item)).to(t).igornNull().copy();
                dataList.add(t);

            });
        } catch (BeanException e) {
            //appClassLoader有问题，吃掉异常
            String message = e.getMessage();
            if(message.startsWith("javassist.CannotCompileException")){
                logger.info("class loader error ignore");
            }else {
                throw e;
            }
        }
        return dataList;
    }


    /**
     * 带回调函数的集合数据的拷贝（可自定义字段拷贝规则）
     *
     * @param sources:  数据源类
     * @param target:   目标类::new(eg: UserVO::new)
     * @param callBack: 回调函数
     * @author jian Ye
     * @return
     */
    private static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
        List<T> list = new ArrayList<>(sources.size());

        sources.forEach(i->{
            T t = target.get();
            try {
                BeanUtils.copyProperties(t,i);
                list.add(t);
            } catch (Exception e) {
                logger.error(e);
                throw new RuntimeException("copyProperties error",e);
            }
            if (callBack != null) {
                callBack.callBack(i, t);
            }
        });
        return list;
    }

    @FunctionalInterface
    private interface BeanCopyUtilCallBack <S, T> {
        /**
         * 定义默认回调方法
         * @param t
         * @param s
         * @author jian Ye
         */
        void callBack(S t, T s);
    }




}
